
import { Col } from "../../../../core/data_ext";
import { StrDataWriter, StrDataReader } from "../../../../core/serialize";
import Utils, { Sync } from "../../../../core/utils";
import CharacterPart from "./character_part";

const { executeInEditMode, ccclass, property } = cc._decorator;


export class CharacterArmatureConfig {
    headId = 0;
    colorHex = "ffffff";
    get data() {
        let w = new StrDataWriter();
        w.writeInt(this.headId, 2);
        w.write(this.colorHex);
        return w.str;
    }
    set data(str: string) {
        let r = new StrDataReader(str);
        this.headId = r.readInt(2);
        this.colorHex = r.read(6);
    }
};


@ccclass
@executeInEditMode
export default class CharacterArmature extends cc.Component {
    @property(cc.Node)
    arm: cc.Node = null;
    @property(cc.Animation)
    ani: cc.Animation = null;

    subAniCol: Col<cc.Animation> = {};

    get isFilp() {
        return this.node.scaleX === -1;
    }
    set isFilp(val) {
        this.node.scaleX = val ? -1 : 1;
    }
    _config: CharacterArmatureConfig = new CharacterArmatureConfig();
    get config() {
        return this._config;
    }
    set config(val) {
        if (!cc.isValid(this)) {
            return;
        }
        if (this._config.headId !== val.headId) {
            this._config.headId = val.headId;
            let prefab: cc.Prefab = Utils.loader.getAsset(`Head${this._config.headId}`, "Prefabs", "cc.Prefab");
            if (!prefab) {
                console.warn(`没有找到 Head${this._config.headId}`);
                prefab = Utils.loader.getAsset(`Head0`, "Prefabs", "cc.Prefab");
            }
            let part = cc.instantiate(prefab).getComponent(CharacterPart);
            this.setPart(part);
        }
        if (this._config.colorHex !== val.colorHex) {
            this.color = this.color.fromHEX(val.colorHex);
            this._config.colorHex = val.colorHex;
        }
    }

    @property({
        serializable: true
    })
    _color: cc.Color = cc.color();
    @property
    get color() {
        return this._color;
    }
    set color(val) {
        this._color = val;
        this.refreshPartColor();
    }
    partCol: Col<CharacterPart> = {};
    aniStateCol: Col<string> = {};
    play(aniName: string, stateName = "main") {
        if (this.aniStateCol[stateName] === aniName) {
            return;
        }
        this.aniStateCol[stateName] = aniName;
        if (stateName !== "main") {
            this.subAniCol[stateName].playAdditive(aniName);
        }
        else {
            this.ani.play(aniName);
        }
    }
    refreshPartColor() {
        for (let key in this.partCol) {
            let part = this.partCol[key];
            part.color = this._color;
        }
    }
    onLoad() {
        this.subAniCol["head"] = cc.find("head", this.arm).getComponent(cc.Animation);
        this.arm.getComponentsInChildren(CharacterPart).forEach(part => {
            let key = part.partName;
            this.partCol[key] = part;
            part.init();
        });
        this.refreshPartColor();
    }
    setPart(part: CharacterPart) {
        if (!cc.isValid(part)) {
            return;
        }
        this.ani.stop();
        let key = part.partName;
        if (cc.isValid(this.partCol[key])) {
            this.partCol[key].node.destroy();
            delete this.partCol[key];
        }
        this.partCol[key] = part;
        part.init();

        Utils.ChangeGroupRec(this.arm.group, this.arm.groupIndex, part.node);
        cc.find(key, this.arm).addChild(part.node);
    }

    getPart(partName: string) {
        return this.partCol[partName];
    }
    hasPart(partName: string) {
        return !!this.getPart(partName);
    }

    @property(cc.ParticleSystem)
    dustPac: cc.ParticleSystem = null;

    async pacShot() {
        this.dustPac.angleVar = 100;
        this.dustPac.angle = 90;
        this.dustPac.emissionRate = 100;
        cc.Tween.stopAllByTarget(this.dustPac);
        await Sync.TweenEnd(cc.tween(this.dustPac).delay(0.05));
        this.dustPac.emissionRate = 0;
        this.dustPac.angleVar = 0;
        this.dustPac.angle = 45;
    }

    onStep() {
        // Sound2D.Play(this.node, `step${Random.range(1, 4)}`);
    }
    private static __ArmPrefabCol: Col<cc.Prefab> = {};
    static Create(armName: string, charStyle: string) {
        let prefab: cc.Prefab = null;
        if (this.__ArmPrefabCol[armName]) {
            prefab = this.__ArmPrefabCol[armName];
        }
        else {
            prefab = Utils.loader.getAsset<cc.Prefab>(armName, "Prefabs", "cc.Prefab");
        }

        if (!prefab) {
            console.warn(`CharacterArmature::Create, 没有找到骨架${armName}`);
        }

        let arm = cc.instantiate(prefab).getComponent(CharacterArmature);
        let config = new CharacterArmatureConfig();
        config.data = charStyle;
        arm.config = config;
        return arm;
    }
};